package edu.tongji.structureplayer.file
{
    import edu.tongji.structureplayer.structure.Connection;
    import edu.tongji.structureplayer.structure.Constrain;
    import edu.tongji.structureplayer.structure.Element;
    import edu.tongji.structureplayer.structure.KeyPoint;
    import edu.tongji.structureplayer.structure.Load;
    import edu.tongji.structureplayer.structure.MaterialProperty;
    import edu.tongji.structureplayer.structure.Node;
    import edu.tongji.structureplayer.structure.PiecewiseFunction;
    import edu.tongji.structureplayer.structure.Property;
    import edu.tongji.structureplayer.structure.SectionConstant;
    import edu.tongji.structureplayer.structure.WellBehavedStructure;
    
    import flash.filesystem.File;
    import flash.filesystem.FileMode;
    import flash.filesystem.FileStream;
    
    import mx.controls.Alert;
    
    import org.as3commons.collections.framework.ILinkedList;
    import org.as3commons.collections.framework.ILinkedListIterator;
    import org.as3commons.collections.framework.core.LinkedListIterator;
    
    public class XMLManager implements XMLManagerI
    {
        
        public function exportXML(structure:WellBehavedStructure, file:File):void
        {
            if (null == file)
                return;
            
            if (!file.exists)
            {
                trace(structureToXML(structure));
                /*var stream:FileStream = new FileStream();
                stream.open(file, FileMode.WRITE);
                stream.writeUTFBytes(structureToXML(structure));
                stream.close();*/
            } 
            else 
            {
                Alert.show("File " + file.name + " exists!");
            }
        }
        
        public function structureToXML(structure:WellBehavedStructure):String
        {
            var doc:XML = new XML("<structure></structure>");
            //doc.appendChild(<p>hello</p>);
            if (structure != null) 
            {
                if (structure.nodes != null && structure.nodes.size != 0)
                    appendNodes(structure.nodes, doc);
                if (structure.sectionConstants != null 
                    && structure.sectionConstants.size != 0)
                    appendSectionConstants(structure.sectionConstants, doc);
                if (structure.materialProperties != null 
                    && structure.materialProperties.size != 0)
                    appendMaterialProperties(structure.materialProperties, doc);
                if (structure.properties != null 
                    && structure.properties.size != 0)
                    appendProperties(structure.properties, doc);
                if (structure.piecewiseFunctions != null 
                    && structure.piecewiseFunctions.size != 0)
                    appendPiecewiseFunctions(structure.piecewiseFunctions, doc);
                if (structure.connections != null 
                    && structure.connections.size != 0)
                    appendConnections(structure.connections, doc);
                if (structure.elements != null 
                    && structure.elements.size != 0)
                    appendElements(structure.elements, doc);
                if (structure.keyPoints != null 
                    && structure.keyPoints.size != 0)
                    appendKeyPoints(structure.keyPoints, doc);
                if (structure.constrains != null 
                    && structure.constrains.size != 0)
                    appendConstrains(structure.constrains, doc);
                if (structure.loads != null && structure.loads.size != 0)
                    appendLoads(structure.loads, doc);
            }
            return doc.toXMLString();
        }
        
        public function importXML(file:File):WellBehavedStructure
        {
            return null;
        }
        
        private function appendNodes(nodes:ILinkedList, doc:XML):void
        {
            var nodesXML:XML = new XML("<nodes></nodes>");
            var it:ILinkedListIterator = nodes.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var n:Node = it.current as Node;
                var node:XML = new XML("<node></node>");
                var name:XML = new XML("<name>" + n.name + "</name>");
                var x:XML = new XML("<x>" + n.x + "</x>");
                var y:XML = new XML("<y>" + n.y + "</y>");
                node.appendChild(name);
                node.appendChild(x);
                node.appendChild(y);
                nodesXML.appendChild(node);
            }
            doc.appendChild(nodesXML);
        }
        
        private function appendSectionConstants(sectionConstants:ILinkedList, doc:XML):void
        {
            var constantsXML:XML = new XML("<sectionConstants></sectionConstants>");
            var it:ILinkedListIterator = sectionConstants.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var c:SectionConstant = it.current as SectionConstant;
                var constant:XML = new XML("<sectionConstant></sectionConstant>");
                var name:XML = new XML("<name>" + c.name + "</name>");
                var crossArea:XML = new XML("<crossArea>" + c.crossArea + "</crossArea>");
                var secondMomentOfArea:XML = new XML("<secondMomentOfArea>" + 
                    c.secondMomentOfArea + "</secondMomentOfArea>");
                constant.appendChild(name);
                constant.appendChild(crossArea);
                constant.appendChild(secondMomentOfArea);
                constantsXML.appendChild(constant);
            }
            doc.appendChild(constantsXML);
        }
        
        private function appendMaterialProperties(materialProperties:ILinkedList, doc:XML):void
        {
            var propertiesXML:XML = new XML("<materialProperties></materialProperties>");
            var it:ILinkedListIterator = materialProperties.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var p:MaterialProperty = it.current as MaterialProperty;
                var property:XML = new XML("<materialProperty></materialProperty>");
                var name:XML = new XML("<name>" + p.name + "</name>");
                var elasticModulus:XML = new XML("<elasticModulus>" + 
                    p.elasticModulus + "</elasticModulus>");
                var poissonRatio:XML = new XML("<poissonRatio>" + 
                    p.poissonRatio + "</poissonRatio>");
                property.appendChild(name);
                property.appendChild(elasticModulus);
                property.appendChild(poissonRatio);
                propertiesXML.appendChild(property);
            }
            doc.appendChild(propertiesXML);
        }
        
        private function appendProperties(properties:ILinkedList, doc:XML):void
        {
            var propertiesXML:XML = new XML("<properties></properties>");
            var it:ILinkedListIterator = properties.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var p:Property = it.current as Property;
                var property:XML = new XML("<property></property>");
                var name:XML = new XML("<name>" + p.name + "</name>");
                var sectionConstant:XML = new XML("<sectionConstant " +  
                    "ref=\"" + p.sectionConstant.name + "\"/>");
                var materialProperty:XML = new XML("<materialProperty " +
                    "ref=\"" + p.materialProperty.name + "\"/>");
                property.appendChild(name);
                property.appendChild(sectionConstant);
                property.appendChild(materialProperty);
                propertiesXML.appendChild(property);
            }
            doc.appendChild(propertiesXML);
        }
        
        private function appendPiecewiseFunctions(functions:ILinkedList, doc:XML):void
        {
            var functionsXML:XML = new XML("<piecewiseFunctions></piecewiseFunctions>");
            var it:ILinkedListIterator = functions.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var f:PiecewiseFunction = it.current as PiecewiseFunction;
                var func:XML = new XML("<piecewiseFunction></piecewiseFunction>");
                var name:XML = new XML("<name>" + f.name + "</name>");
                var pointsList:XML = new XML("<points></points>");
                for (var i:uint=0; i<f.xPos.length&&i<f.yPos.length; i++)
                {
                    pointsList.appendChild(new XML("<point x=\"" + f.xPos[i] + "\" y=\"" 
                        + f.yPos[i] + "\"/>"));
                }
                func.appendChild(name);
                func.appendChild(pointsList);
                functionsXML.appendChild(func);
            }
            doc.appendChild(functionsXML);
        }
        
        private function appendConnections(connections:ILinkedList, doc:XML):void
        {
            var connectionsXML:XML = new XML("<connections></connections>");
            var it:ILinkedListIterator = connections.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var c:Connection = it.current as Connection;
                var connection:XML = new XML("<connection></connection>");
                var name:XML = new XML("<name>" + c.name + "</name>");
                var xEnable:XML = new XML("<xEnable>" + c.xEnable + "</xEnable>");
                var yEnable:XML = new XML("<yEnable>" + c.yEnable + "</yEnable>");
                var thetaEnable:XML = new XML("<thetaEnable>" + c.thetaEnable + "</thetaEnable>");
                connection.appendChild(name);
                connection.appendChild(xEnable);
                connection.appendChild(yEnable);
                connection.appendChild(thetaEnable);
                if (c.func != null)
                    connection.appendChild(new XML("<piecewiseFunction ref=\"" + 
                        c.func.name +"\"/>"));
                connectionsXML.appendChild(connection);
            }
            doc.appendChild(connectionsXML);
        }
        
        private function appendElements(elements:ILinkedList, doc:XML):void
        {
            var elementsXML:XML = new XML("<elements></elements>");
            var it:ILinkedListIterator = elements.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var e:Element = it.current as Element;
                var element:XML = new XML("<element></element>");
                var name:XML = new XML("<name>" + e.name + "</name>");
                var startNode:XML = new XML("<startNode ref=\"" + e.startNode.name 
                    + "\"/>");
                var startConn:XML = new XML("<startConnection ref=\"" + e.startConnection.name 
                    + "\"/>");
                var endNode:XML = new XML("<endNode ref=\"" + e.endNode.name 
                    + "\"/>");
                var endConn:XML = new XML("<endConnection ref=\"" + e.endConnection.name 
                    + "\"/>");
                element.appendChild(name);
                element.appendChild(startNode);
                element.appendChild(endNode);
                element.appendChild(startConn);
                element.appendChild(endConn);
                elementsXML.appendChild(element);
            }
            doc.appendChild(elementsXML);
        }
        
        private function appendKeyPoints(keyPoints:ILinkedList, doc:XML):void
        {
            var keyPointsXML:XML = new XML("<keyPoints></keyPoints>");
            var it:ILinkedListIterator = keyPoints.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var k:KeyPoint = it.current as KeyPoint;
                var keyPoint:XML = new XML("<keyPoint></keyPoint>");
                var name:XML = new XML("<name>" + k.name + "</name>");
                var direction:XML = new XML("<direction>" + k.direction + "</direction>");
                var position:XML = new XML("<position>" + k.position + "</position>");
                var strength:XML = new XML("<strength>" + k.strength + "</strength>");
                keyPoint.appendChild(name);
                keyPoint.appendChild(direction);
                keyPoint.appendChild(position);
                keyPoint.appendChild(strength);
                keyPointsXML.appendChild(keyPoint);
            }
            doc.appendChild(keyPointsXML);
        }
        
        private function appendConstrains(constrains:ILinkedList, doc:XML):void
        {
            var constrainsXML:XML = new XML("<constrains></constrains>");
            var it:ILinkedListIterator = constrains.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var c:Constrain = it.current as Constrain;
                var constrain:XML = new XML("<constrain></constrain>");
                var name:XML = new XML("<name>" + c.name + "</name>");
                var conn:XML = new XML("<connection ref=\"" +c.connection.name + "\"/>");
                var node:XML = new XML("<node ref=\"" +c.node.name + "\"/>");
                var theta:XML = new XML("<theta>" + c.theta + "</theta>");
                constrain.appendChild(name);
                constrain.appendChild(conn);
                constrain.appendChild(node);
                constrain.appendChild(theta);
                constrainsXML.appendChild(constrain);
            }
            doc.appendChild(constrainsXML);
        }
        
        private function appendLoads(loads:ILinkedList, doc:XML):void
        {
            var loadsXML:XML = new XML("<loads></loads>");
            var it:ILinkedListIterator = loads.iterator() as ILinkedListIterator;
            while (it.hasNext())
            {
                it.next();
                var l:Load = it.current as Load;
                var load:XML = new XML("<load></load>");
                var name:XML = new XML("<name>" + l.name + "</name>");
                load.appendChild(name);
                if (l.node == null)
                {
                    var element:XML = new XML("<element ref=\"" +l.element.name + "\"/>");
                    var startKeyPoint:XML = new XML("<startKeyPoint ref=\"" +l.startKeyPoint.name + "\"/>");
                    var endKeyPoint:XML = new XML("<endKeyPoint ref=\"" +l.endKeyPoint.name + "\"/>");
                    load.appendChild(element);
                    load.appendChild(startKeyPoint);
                    load.appendChild(endKeyPoint);
                }
                else
                {
                    var node:XML = new XML("<node ref=\"" + l.node.name + "\"/>");
                    var strength:XML = new XML("<strength>" + l.strength + "</strength>");
                    var direction:XML = new XML("<direction>" + l.direction + "</direction>");
                    load.appendChild(node);
                    load.appendChild(strength);
                    load.appendChild(direction);
                }
                var type:XML = new XML("<type>" + l.type + "</type>");
                load.appendChild(type);
                loadsXML.appendChild(load);
            }
            doc.appendChild(loadsXML);
        }
    }
}